// 导入axios库和类型定义
import axios, { type AxiosInstance } from 'axios'
import { requestManager } from './requestManager' // 请求管理器，用于处理重复请求和取消请求
import webConfig from '@/config/webConfig' // 配置文件，包含API白名单、密钥等
import { useUserStore } from '@/stores' // Vuex或Pinia用户存储，用于获取用户信息和Token
import router from '@/router' // Vue路由实例，用于页面跳转
import { showFailToast } from 'vant' // Vant UI库的Toast组件，用于显示错误信息
import 'vant/es/toast/style'

// 创建一个Axios实例，并配置基础URL、超时时间、响应类型和头部信息
const request: AxiosInstance = axios.create({
  baseURL: '/api/user', // API的基础URL
  timeout: 60 * 1000, // 请求超时时间，单位毫秒
  responseType: 'json', // 期望服务器返回的数据类型
  headers: {
    'Content-Type': 'application/json;charset=UTF-8;application/javascript', // 发送请求时的头部信息
  },
})

// 添加请求拦截器
request.interceptors.request.use(
  (config) => {
    // 获取白名单API列表
    const whiteList = webConfig.whiteListApi as string[]
    const url = config.url as string

    const token = localStorage.getItem('token')

    // 如果当前URL不在白名单中且存在Token，则将Token添加到请求头部
    if (
      !whiteList.some((whiteUrl) => {
        const regex = new RegExp(`^${whiteUrl.replace(/\*/g, '.*')}$`)
        return regex.test(url)
      }) &&
      token
    ) {
      // 将Token添加到请求头部
      config.headers['Authentication'] = token
    }

    // 创建取消令牌源，用于取消重复或未完成的请求
    const cancelTokenSource = axios.CancelToken.source()
    config.cancelToken = cancelTokenSource.token

    // 检查是否存在重复请求，如果存在则取消当前请求
    if (requestManager.isDuplicateRequest(config)) {
      cancelTokenSource.cancel('检测到重复请求')
      return Promise.reject(new Error('重复请求'))
    }

    // 将当前请求添加到待处理请求列表中
    requestManager.addPendingRequest(config, cancelTokenSource)

    // 返回配置对象，继续请求流程
    return config
  },
  (error) => {
    // 请求错误处理，可以记录日志或显示错误信息
    return Promise.reject(new Error(`请求错误: ${error.message}`))
  },
)

// 添加响应拦截器
request.interceptors.response.use(
  (response) => {
    const { code, msg } = response.data
    const config = response.config

    // 从待处理请求列表中移除当前请求
    if (config && config.cancelToken) {
      requestManager.removePendingRequest(config.url!, config.method!)
    }

    // 根据响应码处理响应数据
    if (code !== 1) {
      // 非成功响应码，显示错误信息并使用Promise.reject抛出错误
      showFailToast(msg)
      return Promise.reject(new Error(msg))
    }

    // 成功响应，直接返回响应数据
    return response.data
  },
  (error) => {
    // 响应错误处理
    if (!error.response) {
      // 网络错误，请求未成功发送到服务器
      return Promise.reject(new Error('网络异常，请检查您的网络连接'))
    }

    const { status } = error.response
    const userStore = useUserStore()

    // 根据HTTP状态码处理不同类型的错误
    if (status === 401) {
      // 未授权，清除用户信息并重定向到登录页面
      userStore.removeUser()
      showFailToast('当前未登录,请先登录')
      // 跳转到登录页面并传递当前页面的路径作为返回地址
      router.push(`/login?returnUrl=${router.currentRoute.value.fullPath}`)
    } else if (status >= 400 && status < 500) {
      // 客户端错误（4xx），可以根据具体状态码进行更细致的处理
      console.error(`客户端错误: ${status}`)
    } else if (status >= 500) {
      // 服务器错误（5xx），可以根据具体状态码进行更细致的处理
      console.error(`服务器错误: ${status}`)
    } else {
      // 其他未知的HTTP状态码
      console.error(`未知错误: ${status}`)
    }

    // 使用Promise.reject抛出错误，以便在调用请求的地方进行错误处理
    return Promise.reject(new Error(`HTTP状态码错误: ${status}`))
  },
)

// 导出Axios实例，供其他模块使用
export default request
